from datetime import datetime, date
from pydantic import BaseModel, ValidationError, constr
from typing import List, Optional
from pathlib import Path
import json
from sqlalchemy import Column, Integer, String
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base

# class User(object):
class User(BaseModel):
    id: int
    name: str = "Someone Name"
    signup_ts: Optional[datetime] = None
    friends: List[int] = []  # 列表中的类型必须int类型或可以直接转换为int类型的字符串


external_data = {
  "id": '2',
  "name": "李磊",
  "signup_ts": "2022-12-12 12:12",
  "friends": [1, 2, "3"]
}

print('\033[1;45m 1.通过字典展开新建对象 \033[0m')
user = User(**external_data)
print(user.name)
print(user.dict())

print('\033[1;45m 2.特殊字段一个个赋值 \033[0m')
try:
    user2 = User(id='5', signup_ts="2018-12-12 12:12:12", friends=[6, 7])
    print(user2.name)
    print(user2.dict())

except ValidationError as e:
    print('ValidationError')
    print(e.json())

print('\033[1;45m 3.其他生成对象的方法 \033[0m')
try:
    user3 = User.parse_obj(obj=external_data)
    print(user3)
    print(User.parse_raw(json.dumps(external_data)))
    print('user3.dict()：', user3.dict())
    print('user3.json()：', user3.json())
    print(user3.copy())  # 浅拷贝
    path = Path('userObjStr.json')
    user4 = User.parse_file(path)
    print(user4.dict())
    print("user4.schema()：", user4.schema())
    print("user4.schema_json()：", user4.schema_json())
    print(User.construct)
    external_data_error = {
      "id": 'a2',
      "name": "李磊",
      "signup_ts": "2022-12-12 12:12",
      "friends": [1, 2, "3"]
    }
    print('123456', User.construct(**external_data_error))  # 不校验
    print(User.__fields__.keys())
    print('\033[1;45m 4.递归模型 \033[0m')

    class Sound(BaseModel):
        sound: str

    class Dog(BaseModel):
        birthday: date
        weight: float = Optional[None]
        sound: List[Sound]

    dogs = Dog(birthday=date.today(), weight=6.6, sound=[{"sound": 'wanwan'}, {"sound": 'yinying'}])
    print(dogs.dict())
    print('\033[1;45m 5.ORM模型 从类实例创建符合ORM对象的模型 \033[0m')

    Base = declarative_base()

    class CompanyOrm(Base):
        __tablename__ = 'companies'
        id = Column(Integer, primary_key=True, nullable=False)
        public_key = Column(String(20), index=True, nullable=False, unique=True)
        name = Column(String(64), unique=True)
        domains = Column(ARRAY(String(255)))

    class CompanyMode(BaseModel):
        id: int
        public_key: constr(max_length=20)
        name: constr(max_length=64)
        domains: List[constr(max_length=255)]

        class Config:
            orm_mode = True

    # orm模型类的实例
    co_orm = CompanyOrm(
      id=123,
      public_key='1234455',
      name='Testing',
      domains=['baidu.com', 'sina.com', 'qq.com']
    )
    print(CompanyMode.from_orm(co_orm))  # 把orm模型类的实例格式化为pydanic格式化后的实例

except ValidationError as e:
    print('ValidationError')
    print(e.json())
